package com.github.jcooky.structure;

public class ArraySequence implements Sequence {
	private ArrayList list;
	
	private class ArrayNode extends Node {
		int index;
		
		public ArrayNode(int index) {
			this.index = index;
		}
		
		public Object element() {
			return list.get(index);
		}

		public void setElement(Object e) {
			list.set(index, e);
		}

		public void setPrev(Node p) {
			list.set(index - 1, p.element());
		}

		public void setNext(Node p) {
			list.set(index + 1, p.element());
		}

		public Node getPrev() {
			return atIndex(index - 1);
		}

		public Node getNext() {
			return atIndex(index + 1);
		}

		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + index;
			return result;
		}

		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			ArrayNode other = (ArrayNode) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (index != other.index)
				return false;
			return true;
		}

		private ArraySequence getOuterType() {
			return ArraySequence.this;
		}

		public String toString() {
			return "ArrayNode [index=" + index + "]";
		}
		
	}

	public Object get(int i) {
		return list.get(i);
	}

	public Object set(int i, Object e) {
		return list.set(i, e);
	}

	public void add(int i, Object e) {
		list.add(i, e);
	}

	public Object remove(int i) {
		return list.remove(i);
	}

	public int size() {
		return list.size();
	}

	public boolean isEmpty() {
		return list.isEmpty();
	}

	public Node first() {
		return atIndex(0);
	}

	public Node last() {
		return atIndex(list.size() - 1);
	}

	public Node prev(Node p) {
		return p.getPrev();
	}

	public Node next(Node p) {
		return p.getNext();
	}

	public void set(Node p, Object e) {
		list.set(indexOf(p), e);
	}

	public void addBefore(Node p, Object e) {
		list.add(indexOf(p), e);
	}

	public void addAfter(Node p, Object e) {
		list.add(indexOf(p)+1, e);
	}

	public void addFirst(Object e) {
		list.add(0, e);
	}

	public void addLast(Object e) {
		list.add(list.size(), e);
	}

	public Object remove(Node p) {
		return list.remove(indexOf(p));
	}

	public Node atIndex(int i) {
		return new ArrayNode(i);
	}

	public int indexOf(Node p) {
		return ((ArrayNode)p).index;
	}
	
	public Iterator iterator() {
		return list.iterator();
	}
}
